package com.wzy.content.service.jobhandler;

import com.wzy.base.exception.CustomException;
import com.wzy.content.feignclient.CourseIndex;
import com.wzy.content.feignclient.SearchServiceClient;
import com.wzy.content.mapper.CoursePublishMapper;
import com.wzy.content.model.po.CoursePublish;
import com.wzy.content.service.PreviewPublishService;
import com.wzy.messagesdk.model.po.MqMessage;
import com.wzy.messagesdk.service.MessageProcessAbstract;
import com.wzy.messagesdk.service.MqMessageService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;

/**
 * @Author wzy
 * @Date 2024/1/20 19:58
 * @description: 课程发布后续一系列任务处理
 */
@Slf4j
@Component
public class CoursePublishTask extends MessageProcessAbstract {
    @Autowired
    private PreviewPublishService previewPublishService;
    @Autowired
    private CoursePublishMapper coursePublishMapper;
    @Autowired
    private SearchServiceClient searchServiceClient;

    //任务调度入口
    @XxlJob("CoursePublishJobHandler")
    public void coursePublishJobHandler() throws Exception {
        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        log.debug("shardIndex="+shardIndex+",shardTotal="+shardTotal);
        //参数:分片序号、分片总数、消息类型、一次最多取到的任务数量、一次任务调度执行的超时时间
        process(shardIndex,shardTotal,"course_publish",30,60);
    }

    /**
     * 课程发布任务处理
     * @param mqMessage 执行任务内容
     * @return
     */
    @Override
    public boolean execute(MqMessage mqMessage) {
        //获取消息相关的业务信息
        String businessKey1 = mqMessage.getBusinessKey1();
        long courseId = Integer.parseInt(businessKey1);
        //课程静态化
        generateCourseHtml(mqMessage,courseId);
        //课程索引
        saveCourseIndex(mqMessage,courseId);
        //课程缓存
        saveCourseCache(mqMessage,courseId);
        return true;
    }

    /**
     * 生成课程静态化页面并上传至文件系统 第一阶段
     * @param mqMessage 待处理信息
     * @param courseId 课程id
     */
    private void generateCourseHtml(MqMessage mqMessage, long courseId) {
        log.debug("开始进行课程静态化,课程id:{}",courseId);
        //幂等性处理
        //查出该阶段的执行状态
        //获得该消息的id
        Long id = mqMessage.getId();
        //注入message—sdk模块中的service
        MqMessageService mqMessageService = this.getMqMessageService();
        //通过service调用getStageOne方法获得第一阶段的执行状态
        int stageOne = mqMessageService.getStageOne(id);
        if(stageOne>0){
            log.debug("课程静态化已处理过，无需再处理，课程id:{}",courseId);
            return ;
        }
        //开始执行课程页面静态化
        //生成静态化页面
        File file = previewPublishService.generateCourseHtml(courseId);
        //上传静态化页面
        if(file!=null){
            previewPublishService.uploadCourseHtml(courseId,file);
        }
        //执行完成 设置第一阶段的状态
        mqMessageService.completedStageOne(id);

    }

    /**
     * 保存课程索引信息到elasticsearch 第二阶段
     * @param mqMessage 待处理信息
     * @param courseId 课程id
     */
    private void saveCourseIndex(MqMessage mqMessage, long courseId) {
        log.debug("开始进行插入elasticsearch课程索引,课程id:{}",courseId);
        //幂等性处理
        //查出该阶段的执行状态
        //获得该消息的id
        Long id = mqMessage.getId();
        //注入message—sdk模块中的service
        MqMessageService mqMessageService = this.getMqMessageService();
        //通过service调用getStageOne方法获得第一阶段的执行状态
        int stageOne = mqMessageService.getStageTwo(id);
        if(stageOne>0){
            log.debug("elasticsearch课程索引已经插入过，无需再插入，课程id:{}",courseId);
            return ;
        }
        //开始将课程索引插入elasticsearch
        //取出课程发布信息
        CoursePublish coursePublish = coursePublishMapper.selectById(courseId);
        //拷贝至课程索引对象
        CourseIndex courseIndex = new CourseIndex();
        BeanUtils.copyProperties(coursePublish,courseIndex);
        //远程调用搜索服务api添加课程信息到索引
        Boolean add = searchServiceClient.add(courseIndex);
        if(!add){
            throw new CustomException("添加索引失败");
        }

        //执行完成 设置二阶段的状态
        mqMessageService.completedStageTwo(id);
    }



    /**
     * 将课程信息缓存至redis 第三阶段
     * @param mqMessage 待处理信息
     * @param courseId 课程id
     */
    private void saveCourseCache(MqMessage mqMessage, long courseId) {
        log.debug("开始将课程信息缓存至redis,课程id:{}",courseId);
        //幂等性处理
        //查出该阶段的执行状态
        //获得该消息的id
        Long id = mqMessage.getId();
        //注入message—sdk模块中的service
        MqMessageService mqMessageService = this.getMqMessageService();
        //通过service调用getStageOne方法获得第一阶段的执行状态
        int stageOne = mqMessageService.getStageThree(id);
        if(stageOne>0){
            log.debug("课程信息已缓存过redis，无需再缓存，课程id:{}",courseId);
            return ;
        }
        //开始将课程信息缓存至redis todo

        //执行完成 设置三阶段的状态
        mqMessageService.completedStageThree(id);
    }

}
